﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using BinhSon.Dao;
using BinhSon.Services.Const;

namespace BinhSon.Services.Impl
{
    public partial class BinhSonServices
    {        
        public void ThemMonHoc(MonHoc mh)
        {
            if (this.CheckExistMonHoc(mh.TenMonHoc))
            {
                var monHoc = this._bsEntities.MonHoc.SingleOrDefault(x => x.TenMonHoc == mh.TenMonHoc);
                if (monHoc == null) return;
                monHoc.KyHieuMonHoc = mh.KyHieuMonHoc;
                this._bsEntities.SaveChanges();
            }
            else
            {
                this._bsEntities.MonHoc.Add(mh);
                this._bsEntities.SaveChanges();    
            }
        }

        public bool CheckExistMonHoc(string tenMonHoc)
        {
            var monHoc = this._bsEntities.MonHoc.SingleOrDefault(x => x.TenMonHoc == tenMonHoc);
            return monHoc != null;
        }

        public IList<SystemLookup> ListKhoi()
        {
            return this._bsEntities.SystemLookup.Where(x => x.LookupTypeId == (int) SystemLookupConst.Khoi).ToList();
        }

        public IList<MonHoc> ListMonHoc(int? khoiId = null)
        {
            if (!khoiId.HasValue)
            {
                return this._bsEntities.MonHoc.ToList();    
            }
            return this._bsEntities.MonHocCuaKhoi.Where(x => x.KhoiId == khoiId.Value).Select(x => x.MonHoc).ToList();
        }

        public void ThemMonHocCuaKhoi(MonHocCuaKhoi mhck)
        {
            if (this.CheckExistMonHocTheoKhoi(mhck.KhoiId, mhck.MonHocId))
            {
                var mhtk =
                    this._bsEntities.MonHocCuaKhoi.SingleOrDefault(
                        x => x.KhoiId == mhck.KhoiId && x.MonHocId == mhck.MonHocId);
                if (mhtk == null) return;
                mhtk.SoLan15Phut = mhck.SoLan15Phut;
                mhtk.SoLan1Tiet = mhck.SoLan1Tiet;
                mhtk.SoLanCuoiKy = mhck.SoLanCuoiKy;
                this._bsEntities.SaveChanges();
            }
            else
            {
                this._bsEntities.MonHocCuaKhoi.Add(mhck);
                this._bsEntities.SaveChanges();   
            }            
        }

        public bool CheckExistMonHocTheoKhoi(int khoiId, int monHocId)
        {
            var mhtk = this._bsEntities.MonHocCuaKhoi.SingleOrDefault(x => x.KhoiId == khoiId && x.MonHocId == monHocId);
            return mhtk != null;
        }

        public IList<SystemLookup> ListLanThi()
        {
            return this._bsEntities.SystemLookup.Where(x => x.LookupTypeId == (int) SystemLookupConst.LanThi).ToList();
        }

        public IList<SystemLookup> ListHocKy()
        {
            return this._bsEntities.SystemLookup.Where(x => x.LookupTypeId == (int)SystemLookupConst.HocKy).ToList();
        }

        public bool CheckExistMonHocCuaHocKy(int hocKyId, int khoiId, int monHocId, int lanThiId, int heSo)
        {
            var currentYear = this._bsEntities.ConstantTable.Select(x => x.NamHocHienTai).SingleOrDefault();
            var mhchk =
                this._bsEntities.MonHocCuaHocKy.SingleOrDefault(
                    x =>
                        x.HocKyId == hocKyId && x.KhoiId == khoiId && x.MonHocId == monHocId && x.LanThiId == lanThiId &&
                        x.HeSo == heSo && x.NamHocId == currentYear);
            return mhchk != null;
        }

        public IList<NamHoc> ListNamHoc()
        {
            return this._bsEntities.NamHoc.ToList();
        }

        public void SaveCurrentYear(int namHocId)
        {
            var current = this._bsEntities.ConstantTable.SingleOrDefault();
            if (current == null)
            {
                current = new ConstantTable
                {
                    NamHocHienTai = namHocId
                };
                this._bsEntities.ConstantTable.Add(current);
            }
            else
            {
                current.NamHocHienTai = namHocId;
            }
            this._bsEntities.SaveChanges();
        }

        public NamHoc GetCurrentYear()
        {
            var currentYear = this._bsEntities.ConstantTable.Select(x => x.NamHocHienTai).SingleOrDefault();
            return currentYear == 0 ? null : this._bsEntities.NamHoc.SingleOrDefault(x => x.NamHocId == currentYear);
        }

        public bool ThemMonHocCuaHocKy(MonHocCuaHocKy mhchk)
        {
            var currentYear = this._bsEntities.ConstantTable.Select(x => x.NamHocHienTai).SingleOrDefault();
            mhchk.NamHocId = currentYear;
            this._bsEntities.MonHocCuaHocKy.Add(mhchk);
            this._bsEntities.SaveChanges();

            this.GeneratePhongThi(mhchk);
            return true;
        }

        public MonHocCuaKhoi GetMonHocCuaKhoi(int khoiId, int monHocId)
        {
            return this._bsEntities.MonHocCuaKhoi.SingleOrDefault(x => x.KhoiId == khoiId && x.MonHocId == monHocId);
        }

        private void GeneratePhongThi(MonHocCuaHocKy mhchk)
        {
            //get ds lop cua khoi
            var dsLop = this._bsEntities.LopHoc.Where(x => x.KhoiId == mhchk.KhoiId).ToList();            
            foreach (var lopHoc in dsLop)
            {                
                //chia lop lam 2
                var maxLop1 = (int)lopHoc.SiSoLop/2;
                //phong 1                
                var dsHocSinh1 = lopHoc.HocSinh.Where(x => x.SoThuTu <= maxLop1).ToList();
                //create phong thi 1
                var pt1 = new PhongThi
                {
                    LopHocId = lopHoc.LopHocId,
                    MonHocCuaHocKyId = mhchk.MonHocCuaHocKyId,
                    MaPhongThi = this.GenerateMaPhongThi(mhchk)
                };
                this._bsEntities.PhongThi.Add(pt1);                

                //phong 2                
                var dsHocSinh2 = lopHoc.HocSinh.Where(x => x.SoThuTu > maxLop1).ToList();
                //create phong thi 2
                var pt2 = new PhongThi
                {
                    LopHocId = lopHoc.LopHocId,
                    MonHocCuaHocKyId = mhchk.MonHocCuaHocKyId,
                    MaPhongThi = this.GenerateMaPhongThi(mhchk)
                };
                this._bsEntities.PhongThi.Add(pt2);
                this._bsEntities.SaveChanges();

                //generate ds phong thi hoc sinh
                this.GeneratePhongThiHocSinh(pt1.PhongThiId, dsHocSinh1);
                this.GeneratePhongThiHocSinh(pt2.PhongThiId, dsHocSinh2);                
            }
        }

        private string GenerateMaPhongThi(MonHocCuaHocKy mhchk)
        {            
            var currentYear = this._bsEntities.ConstantTable.Select(x => x.NamHocHienTai).SingleOrDefault();
            var kyHieuNamHoc =
                this._bsEntities.NamHoc.Where(x => x.NamHocId == currentYear)
                    .Select(x => x.KyHieuNamHoc)
                    .SingleOrDefault();
            var result =  kyHieuNamHoc + this.GenerateSoHaiChuSo(mhchk.LanThiId) + mhchk.MonHoc.KyHieuMonHoc + this.CreateRandomString(3);
            return result;
        }

        private void GeneratePhongThiHocSinh(int phongThiId, IEnumerable<HocSinh> dsHocSinh)
        {
            var count = 0;
            foreach (var hocSinh in dsHocSinh)
            {
                count++;
                var pths = new PhongThiHocSinh
                {
                    PhongThiId = phongThiId,
                    HocSinhId = hocSinh.HocSinhId,
                    SoThuTu = count
                };
                this._bsEntities.PhongThiHocSinh.Add(pths);
            }
            this._bsEntities.SaveChanges();
        }

        private string CreateRandomString(int length)
        {
            const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
            var res = new StringBuilder();
            var rnd = new Random();
            while (0 < length--)
            {
                res.Append(valid[rnd.Next(valid.Length)]);
            }
            return res.ToString();
        }

        private string GenerateSoHaiChuSo(int so)
        {
            if (so >= 10)
            {
                return so.ToString();
            }
            return "0" + so.ToString();
        }
    }
}
